package org.msn.gui.controller;

import lombok.SneakyThrows;
import org.msn.gui.init.SelfSoundAndVideoInit;

import javax.sound.sampled.*;
import java.io.IOException;
import java.net.*;
import java.util.ResourceBundle;

public class SelfSoundController extends SelfSoundAndVideoInit {
    public static volatile boolean stop = false;
    private AudioFormat audioFormat;
    private TargetDataLine targetDataLine;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        new SelfSoundThread().start();
    }

    public class SelfSoundThread extends Thread {
        @SneakyThrows
        @Override
        public void run() {
            capture();
        }

        private void capture() throws LineUnavailableException {
            audioFormat = getAudioFormat();
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
            targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
            targetDataLine.open(audioFormat);
            targetDataLine.start();

            Record record = new Record();
            record.start();
        }

        private AudioFormat getAudioFormat() {
            AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
            float rate = 8000f;
            int sampleSize = 16;
            boolean bigEndian = true;
            int channels = 1;

            return new AudioFormat(encoding,
                    rate,
                    sampleSize,
                    channels,
                    (sampleSize / 8) * channels,
                    rate,
                    bigEndian);
        }
    }

    public class Record extends Thread {
        @Override
        public void run() {
            try {
                byte[] bytes = new byte[10240];
                DatagramSocket datagramSocket = new DatagramSocket();

                while (true) {
                    int cnt = targetDataLine.read(bytes, 0, bytes.length);

                    if (cnt > 0) {
                        userIP.stream().forEach((v) -> {
                            try {
                                String[] str = v.split(":");
                                sendSoundToOther(datagramSocket, bytes, InetAddress.getByName(str[0]), Integer.parseInt(str[1]));
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                    }

                    Thread.sleep(50);
                }
            } catch (InterruptedException | SocketException e) {
                e.printStackTrace();
            } finally {
                closeSoundEvent();
            }
        }

        private void sendSoundToOther(DatagramSocket datagramSocket, byte[] bytes, InetAddress remoteIP, int remotePort)
                throws IOException {
            DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, remoteIP, remotePort);
            datagramSocket.send(datagramPacket);
        }

        private void closeSoundEvent() {
            targetDataLine.drain();
            targetDataLine.close();
        }
    }
}
